﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Hack.Hash
{
    class Hash
    {
        /**/
        /** 
        * 改进的32位FNV算法1 
        * @param data 字符串 
        * @return int值 
        */
        public static int FNVHash1(String data)
        {
            int p = 16777619;
            int hash = 0;
            unchecked { hash = (int)2166136261L; }
            for (int i = 0; i < data.Length; i++)
                hash = (hash ^ data[i]) * p;
            hash += hash << 13;
            hash ^= hash >> 7;
            hash += hash << 3;
            hash ^= hash >> 17;
            hash += hash << 5;
            return hash;
        }


        /**/
        /** 
* RS算法hash 
* @param str 字符串 
*/
        public static int RSHash(String str)
        {
            int b = 378551;
            int a = 63689;
            int hash = 0;

            for (int i = 0; i < str.Length; i++)
            {
                hash = hash * a + str[i];
                a = a * b;
            }

            return (hash & 0x7FFFFFFF);
        }
        /**/
        /* End Of RS Hash Function */

        /**/
        /** 
* JS算法 
*/
        public static int JSHash(String str)
        {
            int hash = 1315423911;

            for (int i = 0; i < str.Length; i++)
            {
                hash ^= ((hash << 5) + str[i] + (hash >> 2));
            }

            return (hash & 0x7FFFFFFF);
        }
        /**/
        /* End Of JS Hash Function */

        /**/
        /** 
* PJW算法 
*/
        public static int PJWHash(String str)
        {
            int BitsInUnsignedInt = 32;
            int ThreeQuarters = (BitsInUnsignedInt * 3) / 4;
            int OneEighth = BitsInUnsignedInt / 8;
            int HighBits = (int)(0xFFFFFFFF << (BitsInUnsignedInt - OneEighth));
            int hash = 0;
            int test = 0;

            for (int i = 0; i < str.Length; i++)
            {
                hash = (hash << OneEighth) + str[i];

                if ((test = hash & HighBits) != 0)
                {
                    hash = ((hash ^ (test >> ThreeQuarters)) & (~HighBits));
                }
            }

            return (hash & 0x7FFFFFFF);
        }
        /**/
        /* End Of P. J. Weinberger Hash Function */

        /**/
        /** 
* ELF算法 
*/
        public static int ELFHash(String str)
        {
            int hash = 0;
            int x = 0;

            for (int i = 0; i < str.Length; i++)
            {
                hash = (hash << 4) + str[i];
                if ((x = (int)(hash & 0xF0000000L)) != 0)
                {
                    hash ^= (x >> 24);
                    hash &= ~x;
                }
            }

            return (hash & 0x7FFFFFFF);
        }
        /**/
        /* End Of ELF Hash Function */

        /**/
        /** 
* BKDR算法 
*/
        public static int BKDRHash(String str)
        {
            int seed = 131; // 31 131 1313 13131 131313 etc.. 
            int hash = 0;

            for (int i = 0; i < str.Length; i++)
            {
                hash = (hash * seed) + str[i];
            }

            return (hash & 0x7FFFFFFF);
        }
        /**/
        /* End Of BKDR Hash Function */

        /**/
        /** 
* SDBM算法 
*/
        public static int SDBMHash(String str)
        {
            int hash = 0;

            for (int i = 0; i < str.Length; i++)
            {
                hash = str[i] + (hash << 6) + (hash << 16) - hash;
            }

            return (hash & 0x7FFFFFFF);
        }
        /**/
        /* End Of SDBM Hash Function */

        /**/
        /** 
* DJB算法 
*/
        public static int DJBHash(String str)
        {
            int hash = 5381;

            for (int i = 0; i < str.Length; i++)
            {
                hash = ((hash << 5) + hash) + str[i];
            }

            return (hash & 0x7FFFFFFF);
        }
        /**/
        /* End Of DJB Hash Function */

        /**/
        /** 
* DEK算法 
*/
        public static int DEKHash(String str)
        {
            int hash = str.Length;

            for (int i = 0; i < str.Length; i++)
            {
                hash = ((hash << 5) ^ (hash >> 27)) ^ str[i];
            }

            return (hash & 0x7FFFFFFF);
        }
        /**/
        /* End Of DEK Hash Function */

        /**/
        /** 
* AP算法 
*/
        public static int APHash(String str)
        {
            int hash = 0;

            for (int i = 0; i < str.Length; i++)
            {
                hash ^= ((i & 1) == 0) ? ((hash << 7) ^ str[i] ^ (hash >> 3)) :
            (~((hash << 11) ^ str[i] ^ (hash >> 5)));
            }

            //      return (hash & 0x7FFFFFFF); 
            return hash;
        }
        /**/
        /* End Of AP Hash Function */

        /**/
        /** 
* JAVA自己带的算法 
*/
        public static int java(String str)
        {
            int h = 0;
            int off = 0;
            int len = str.Length;
            for (int i = 0; i < len; i++)
            {
                h = 31 * h + str[off++];
            }
            return h;
        }

        /**/
        /** 
* 混合hash算法，输出64位的值 
*/
        public static long mixHash(String str)
        {
            long hash = str.GetHashCode();
            hash <<= 32;
            hash |= FNVHash1(str);
            return hash;
        }
    }
}